using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;

public class TextureSizeFix
{
    [MenuItem("GameTools/纹理自适应大小")]
    public static void AutoAdjustTextureSizes()
    {
        string folderPath = EditorUtility.OpenFolderPanel("选择纹理目录", "Assets", "");
        if (string.IsNullOrEmpty(folderPath))
        {
            return;
        }

        // 转换路径为Assets相对路径
        if (folderPath.StartsWith(Application.dataPath))
        {
            folderPath = "Assets" + folderPath.Substring(Application.dataPath.Length);
        }
        else
        {
            EditorUtility.DisplayDialog("错误", "请选择Assets目录下的文件夹", "确定");
            return;
        }

        // 获取所有纹理文件
        string[] textureFiles = Directory.GetFiles(folderPath, "*.*", SearchOption.AllDirectories)
            .Where(file => file.EndsWith(".png") || file.EndsWith(".jpg") || file.EndsWith(".jpeg") || file.EndsWith(".tga") || file.EndsWith(".bmp"))
            .ToArray();

        int processedCount = 0;
        int updatedCount = 0;

        foreach (string filePath in textureFiles)
        {
            string assetPath = filePath.Replace("\\", "/");
            TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;

            if (importer != null)
            {
                processedCount++;

                // 获取原始图片尺寸
                var dimensions = GetOriginalImageDimensions(filePath);
                if (dimensions.HasValue)
                {
                    int width = dimensions.Value.width;
                    int height = dimensions.Value.height;
                    int maxDimension = Mathf.Max(width, height);

                    // 获取最接近的MaxSize选项
                    int newMaxSize = GetClosestMaxSize(maxDimension);

                    // 检查是否需要更新MaxSize
                    bool needsMaxSizeUpdate = importer.maxTextureSize != newMaxSize;
                    
                    // 检查是否需要设置Straight Alpha Texture
                    bool needsAlphaUpdate = false;
                    bool usesSpineShader = UsesSpineSkeletonShader(assetPath);
                    if (usesSpineShader)
                    {
                        bool currentAlphaSetting = importer.alphaIsTransparency;
                        needsAlphaUpdate = !currentAlphaSetting;
                        if (needsAlphaUpdate)
                        {
                            importer.alphaIsTransparency = true;
                            Debug.Log($"设置Straight Alpha Texture: {assetPath}, 原值: {currentAlphaSetting}, 新值: true");
                        }
                        else
                        {
                            Debug.Log($"Straight Alpha Texture已正确设置: {assetPath}, 当前值: {currentAlphaSetting}");
                        }
                    }
                    else
                    {
                        Debug.Log($"不需要设置Straight Alpha Texture: {assetPath}");
                    }

                    // 如果有任何更新，保存并重新导入
                    if (needsMaxSizeUpdate || needsAlphaUpdate)
                    {
                        if (needsMaxSizeUpdate)
                        {
                            importer.maxTextureSize = newMaxSize;
                        }
                        
                        importer.SaveAndReimport();
                        updatedCount++;
                        
                        string updateLog = $"已更新纹理: {assetPath}";
                        if (needsMaxSizeUpdate)
                        {
                            updateLog += $" MaxSize: {newMaxSize}";
                        }
                        if (needsAlphaUpdate)
                        {
                            updateLog += " Straight Alpha Texture: true";
                        }
                        updateLog += $" (原始尺寸: {width}x{height})";
                        
                        Debug.Log(updateLog);
                    }
                }
                else
                {
                    Debug.LogWarning($"无法获取纹理尺寸: {assetPath}");
                }
            }
        }

        EditorUtility.DisplayDialog("完成", $"处理完成!\n处理纹理数量: {processedCount}\n更新纹理数量: {updatedCount}", "确定");
    }

    private static int GetClosestMaxSize(int dimension)
    {
        // Unity支持的MaxSize选项
        int[] maxSizeOptions = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };

        foreach (int size in maxSizeOptions)
        {
            if (dimension <= size)
            {
                return size;
            }
        }

        // 如果尺寸超过最大选项，返回最大值
        return maxSizeOptions[maxSizeOptions.Length - 1];
    }

    private static (int width, int height)? GetOriginalImageDimensions(string filePath)
    {
        try
        {
            using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            using (BinaryReader reader = new BinaryReader(stream))
            {
                string extension = Path.GetExtension(filePath).ToLower();

                if (extension == ".png")
                {
                    return GetPngDimensions(reader);
                }
                else if (extension == ".jpg" || extension == ".jpeg")
                {
                    return GetJpegDimensions(reader);
                }
                else if (extension == ".bmp")
                {
                    return GetBmpDimensions(reader);
                }
                else if (extension == ".tga")
                {
                    return GetTgaDimensions(reader);
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"读取图片尺寸错误: {filePath}\n{e.Message}");
        }

        return null;
    }

    private static (int width, int height)? GetPngDimensions(BinaryReader reader)
    {
        // PNG文件头: 89 50 4E 47 0D 0A 1A 0A
        byte[] pngHeader = reader.ReadBytes(8);
        
        // 查找IHDR块 (49 48 44 52)
        while (reader.BaseStream.Position < reader.BaseStream.Length - 8)
        {
            uint chunkLength = reader.ReadUInt32BigEndian();
            string chunkType = new string(reader.ReadChars(4));
            
            if (chunkType == "IHDR")
            {
                int width = reader.ReadInt32BigEndian();
                int height = reader.ReadInt32BigEndian();
                return (width, height);
            }
            else
            {
                // 跳过当前块的数据和CRC
                reader.BaseStream.Seek(chunkLength + 4, SeekOrigin.Current);
            }
        }
        
        return null;
    }

    private static (int width, int height)? GetJpegDimensions(BinaryReader reader)
    {
        // JPEG文件头: FF D8 FF
        byte[] jpegHeader = reader.ReadBytes(2);
        if (jpegHeader[0] != 0xFF || jpegHeader[1] != 0xD8)
            return null;

        while (reader.BaseStream.Position < reader.BaseStream.Length - 4)
        {
            byte marker = reader.ReadByte();
            if (marker != 0xFF) continue;

            byte markerType = reader.ReadByte();
            
            // SOF0, SOF1, SOF2 markers contain dimension info
            if (markerType >= 0xC0 && markerType <= 0xCF && markerType != 0xC4 && markerType != 0xC8 && markerType != 0xCC)
            {
                ushort length = reader.ReadUInt16BigEndian();
                reader.ReadByte(); // precision
                int height = reader.ReadUInt16BigEndian();
                int width = reader.ReadUInt16BigEndian();
                return (width, height);
            }
            else
            {
                // Skip other markers
                ushort length = reader.ReadUInt16BigEndian();
                if (length < 2) continue;
                reader.BaseStream.Seek(length - 2, SeekOrigin.Current);
            }
        }
        
        return null;
    }

    private static (int width, int height)? GetBmpDimensions(BinaryReader reader)
    {
        // BMP文件头
        reader.BaseStream.Seek(18, SeekOrigin.Begin); // 跳过文件头到尺寸信息位置
        int width = reader.ReadInt32();
        int height = reader.ReadInt32();
        return (width, height);
    }

    private static (int width, int height)? GetTgaDimensions(BinaryReader reader)
    {
        // TGA文件头
        reader.BaseStream.Seek(12, SeekOrigin.Begin); // 跳过文件头到尺寸信息位置
        short width = reader.ReadInt16();
        short height = reader.ReadInt16();
        return (width, height);
    }

    private static bool UsesSpineSkeletonShader(string texturePath)
    {
        try
        {
            string directory = Path.GetDirectoryName(texturePath);
            string textureName = Path.GetFileNameWithoutExtension(texturePath);
            
            // 查找同目录下的所有Material文件
            string[] materialFiles = Directory.GetFiles(directory, "*.mat", SearchOption.TopDirectoryOnly);
            
            Debug.Log($"检查纹理: {texturePath}");
            Debug.Log($"所在目录: {directory}");
            Debug.Log($"找到Material文件: {materialFiles.Length}个");
            
            bool foundSpineMaterial = false;
            
            foreach (string matFile in materialFiles)
            {
                Material material = AssetDatabase.LoadAssetAtPath<Material>(matFile);
                if (material != null && material.shader != null)
                {
                    string shaderName = material.shader.name;
                    bool isSpineShader = shaderName.Contains("Spine") || shaderName.Contains("Skeleton");
                    bool usesTexture = MaterialUsesTexture(material, textureName);
                    
                    Debug.Log($"Material: {Path.GetFileName(matFile)}, Shader: {shaderName}, IsSpine: {isSpineShader}, UsesTexture: {usesTexture}");
                    
                    // 检查是否使用Spine/Skeleton shader并且使用当前纹理
                    if (isSpineShader && usesTexture)
                    {
                        Debug.Log($"找到使用Spine shader并使用纹理的Material: {Path.GetFileName(matFile)}");
                        foundSpineMaterial = true;
                    }
                }
                else
                {
                    Debug.Log($"无法加载Material: {Path.GetFileName(matFile)}");
                }
            }
            
            Debug.Log($"最终结果: 需要设置Straight Alpha Texture = {foundSpineMaterial}");
            return foundSpineMaterial;
        }
        catch (Exception e)
        {
            Debug.LogError($"检查Spine shader时出错: {texturePath}\n{e.Message}");
        }
        
        return false;
    }

    private static bool MaterialUsesTexture(Material material, string textureName)
    {
        // 获取Material的所有纹理属性
        int propertyCount = ShaderUtil.GetPropertyCount(material.shader);
        for (int i = 0; i < propertyCount; i++)
        {
            if (ShaderUtil.GetPropertyType(material.shader, i) == ShaderUtil.ShaderPropertyType.TexEnv)
            {
                string propertyName = ShaderUtil.GetPropertyName(material.shader, i);
                Texture texture = material.GetTexture(propertyName);
                
                if (texture != null && texture.name == textureName)
                {
                    return true;
                }
            }
        }
        
        return false;
    }
}

// 扩展方法用于大端序读取
public static class BinaryReaderExtensions
{
    public static ushort ReadUInt16BigEndian(this BinaryReader reader)
    {
        byte[] bytes = reader.ReadBytes(2);
        return (ushort)((bytes[0] << 8) | bytes[1]);
    }

    public static uint ReadUInt32BigEndian(this BinaryReader reader)
    {
        byte[] bytes = reader.ReadBytes(4);
        return (uint)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);
    }

    public static int ReadInt32BigEndian(this BinaryReader reader)
    {
        byte[] bytes = reader.ReadBytes(4);
        return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
    }
}
